package com.qlyl.modules.information.service.impl;

import com.qlyl.common.api.vo.Result;
import com.qlyl.common.constant.SecretkeyContant;
import com.qlyl.common.util.PasswordUtil;
import com.qlyl.modules.information.entity.AppUser;
import com.qlyl.modules.information.entity.EthTransaction;
import com.qlyl.modules.information.entity.EthWallet;
import com.qlyl.modules.information.ethadapter.EthConst;
import com.qlyl.modules.information.ethadapter.EthRedisCache;
import com.qlyl.modules.information.mapper.EthTransactionMapper;
import com.qlyl.modules.information.mapper.EthWalletMapper;
import com.qlyl.modules.information.service.IEthService;
import com.senlin.ethereum.core.EthAccount;
import com.senlin.ethereum.core.EthClient;
import com.senlin.ethereum.infura.InfuraClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.nio.file.OpenOption;
import java.util.Date;
import java.util.Optional;

@Slf4j
@Service
@EnableAsync
public class EthServiceImpl implements IEthService {

    @Autowired
    private EthClient ethClient;

    @Autowired
    private EthRedisCache ethRedisCache;

    @Autowired
    private EthTransactionMapper ethTransactionMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private EthWalletMapper ethWalletMapper;

    @Autowired
    private InfuraClient.Ropsten ropstenClient;

    public Result<String> transferTo(AppUser appUser, String toAddress, String data) {
        Result<String> result = new Result<>();
        EthWallet ethWalletByQiLian = ethWalletMapper.selectById(appUser.getWalletId());
        String memorizingWords = PasswordUtil.decrypt(ethWalletByQiLian.getMemorizingWords(), SecretkeyContant.SECRET_kEY,SecretkeyContant.SECRET_SALT);

        EthClient.EthWallet ethWallet = ethClient.ethWallet(new EthAccount(memorizingWords));
        ethWallet.transferTo(() -> {
            return new EthClient.EthWallet.RawTransactionBuilder(toAddress)
                    .dataTransaction(data).build();
        }, t -> {
            log.info("=> 交易成功！交易hash：{}", t);
            EthTransaction ethTransaction = new EthTransaction();
            ethTransaction.setTransactionHash(t);
            ethTransaction.setUserId(appUser.getId());
            ethTransaction.setData(data);
            ethTransaction.setStatus(0);
            ethTransaction.setComsumsId(appUser.getConsumersId());
            ethTransaction.setCreateTime(new Date());

            ethTransactionMapper.insert(ethTransaction);
            ethRedisCache.putTransactionHash(t);
            result.success("交易成功");
        }, e -> {
            result.error500(e.getMessage());
        });
        return result;
    }

    @Async
    public void rechargeEthWalletByAsyncAndFree(String address) {

       Optional<InfuraClient.RopstenDonate> ropstenDonate = ropstenClient.requestAndGetEther(address);
       if (!ropstenDonate.isPresent()) {
           redisTemplate.opsForList().rightPush(EthConst.INFURA_ROPSTEN_DONATE_REDIS_KEY, address);
       }
    }
}
